#ifndef ESDL_event_h
#define ESDL_event_h

#include <SDL/SDL.h>
#include "window.h"
#include "../graphics/sprite.h"

/**
 * @enum EventType
 * @brief Enumeration of all ESDL types of events
 */
typedef enum EsdlEventType EsdlEventType;

enum EsdlEventType {
    ON_FOCUS, //!< @brief Trigger when a sprite catch user's focus
    ON_BLUR, //!< @brief Trigger when another sprite catch user's focus
    ON_KEY_UP, //!< @brief Trigger when a keyboard key has been released
    ON_KEY_DOWN, //!< @brief Trigger when a keyboard key has been pressed
    ON_MOUSE_UP, //!< @brief Trigger when a mouse button has been released
    ON_MOUSE_DOWN, //!< @brief Trigger when a mouse button has been pressed
    ON_MOUSE_ENTER, //!< @brief Trigger when the mouse cursor is entering a sprite 
    ON_MOUSE_LEAVE, //!< @brief Trigger when the mouse cursor is leaving a sprite 
    ON_MOUSE_MOVE //!< @brief Trigger when the mouse cursor is moving on a sprite 
};

/**
 * @struct Event
 * @brief Event structure
 */
typedef struct EsdlEvent EsdlEvent;

struct EsdlEvent {
    EsdlEventType eventType; //!< @brief The type of the event @see Enumeration EventType
    SDL_Event* event; //!< @brief A SDL object
    EsdlSprite* sprite; //!< @brief The sprite which have triggered the event
    bool propagate; //!< @brief A flag to determine if the event have to be propagated or not @see Function stopPropagateEvent()
};

typedef void (*EsdlEventCallback)(EsdlEvent*);

/**
 * @struct Listener
 * @brief Listener structure
 */
typedef struct EsdlListener EsdlListener;

struct EsdlListener {
    EsdlEventType eventType; //!< @brief The type of the event which is listening @see Enumeration EventType
    EsdlEventCallback callback; //!< @brief the callback function which will be execute if a corresponding event is triggered
};


////////////////////////////////
///// Event loop functions /////
////////////////////////////////

/**
 * @brief Start the event manager
 * @param void (*callbak)(int) - A callback function which will be execute 
 *        before each screen render. 
 *        Set to NULL if you don't want to use this parameter
 */
void esdlEventLoop(EsdlRenderCallback callback);

/**
 * @brief Stop the event manager and continue the program
 */
void esdlStopEventLoop();



////////////////////////
///// Event helpers ////
////////////////////////

/**
 * @brief If the type of the event is EVENT_ONKEYUP or EVENT_ONKEYDOWN, then this function return the keyboard key which triggered the event
 * @param Event * event - The current event
 * @return The keyboard key which trigger the event
 * @see Key
 */
EsdlKey esdlGetKey(const EsdlEvent* event);

/**
 * @brief If the type of the event is EVENT_ONMOUSEUP or EVENT_ONMOUSEDOWN, then this function return the mouse button which triggered the event
 * @param Event * event - The current event
 * @return The mouse button which trigger the event
 * @see MouseButton
 */
EsdlMouseButton esdlGetMouseButton(const EsdlEvent* event);

/**
 * @param Event * event - The current event
 * @return Return the sprite on which the event was triggered
 */
EsdlSprite* esdlGetSpriteEvent(const EsdlEvent* event);

/**
 * @brief Stop the propagation of the event. Each callback which haven't been executed yet will not be at all.
 * @param Event * event - The current event
 */
void esdlStopPropagateEvent(EsdlEvent* event);

#endif
